Carregar dados

dados_originais <- read.csv("spotify_data.csv")
aux <- sample(1:nrow(dados_originais), size=nrow(dados_originais)*0.005)
dados <- dados_originais[aux,-c(1:4)]

dados2 <- dados[dados$year==2022,]
dados3 <- dados2[,-c(2,3,6,8,16)]
#variaveis categoricas: c(2,3,6,8,16)

Carregar pacotes

library(dplyr)
library(ggplot2)
library(GGally)
library(corrplot)
library(factoextra)
library(gridExtra)
library(plotly)

Descritiva

Popularity

ggplotly(ggplot(data = dados2, aes(x = popularity)) +
  geom_histogram(color = "black", fill = "steelblue") +
  labs(x = 'Popularidade'))
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Year

ggplotly(ggplot(data = dados2, aes(x = year)) +
  geom_bar(color = "black", fill = "steelblue") +
  labs(x = 'Ano'))

Danceability

ggplotly(ggplot(data = dados2, aes(x = danceability)) +
  geom_histogram(color = "black", fill = "steelblue") +
  labs(x = 'Dançabilidade',y="Frequencia"))
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Energy

ggplotly(ggplot(data = dados2, aes(x = energy)) +
  geom_histogram(color = "black", fill = "steelblue") +
  labs(x = 'Energia'),y="Frequencia")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Key

ggplotly(ggplot(data = dados2, aes(x = key)) +
             geom_bar(color = "black", fill = "steelblue") +
             scale_x_continuous(breaks=seq(0,11,by=1),labels = c("C","C#","D","D#","E","F","F#","G","G#","A","A#","B")) +
             scale_y_continuous(breaks=seq(0,150000,by=25000),labels=c("0","25","50","75","100","125","150")) +
             labs(x = 'Tom',y='Frequencia'))

Loudness

ggplotly(ggplot(data = dados2, aes(x = loudness)) +
             geom_histogram(color = "black", fill = "steelblue") +
             scale_x_continuous(breaks=seq(15,60,by=5)) +
             scale_y_continuous(breaks=seq(0,300000,by=50000),labels=c("0","50","100","150","200","250","300")) +
             labs(x = 'Decibéis',y = 'Frequencia'))
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Mode

ggplotly(ggplot(data = dados2, aes(x = mode)) +
  geom_bar(color = "black", fill = "steelblue") +
  scale_x_continuous(breaks = c(0,1),labels = c("Menor","Maior")) +
  scale_y_continuous(breaks=seq(0,700000,by=100000),labels=c("0","100","200","300","400","500","600","700")) +
  labs(x = 'Escala',y = 'Frequencia'))

Speechiness

ggplotly(ggplot(data = dados2, aes(x = speechiness)) +
             geom_histogram(color = "black", fill = "steelblue") +
             scale_y_continuous(breaks=seq(0,600000,by=100000),labels=c("0","100","200","300","400","500","600")) +
             labs(x = 'Fala',y = 'Frequencia'))
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Acousticness

ggplotly(ggplot(data = dados2, aes(x = acousticness)) +
             geom_histogram(color = "black", fill = "steelblue") +
             scale_y_continuous(breaks=seq(0,400000,by=100000),labels=c("0","100","200","300","400")) +
             labs(x = 'Acusticidade',y="Frequencia"))
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Instrumentalness

ggplotly(ggplot(data = dados2, aes(x = instrumentalness)) +
  geom_histogram(color = "black", fill = "steelblue") +
    scale_y_continuous(breaks=seq(0,700000,by=100000),labels=c("0","100","200","300","400","500","600","700")) +
    labs(x = 'Instrumentalidade',y="Frequencia"))
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Liveness

ggplotly(ggplot(data = dados2, aes(x = liveness)) +
             geom_histogram(color = "black", fill = "steelblue") +
             scale_y_continuous(breaks=seq(0,300000,by=100000),labels=c("0","100","200","300")) +
             labs(x="Presença de audiência",y="Frequencia"))
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Valence

ggplotly(ggplot(data = dados2, aes(x = valence)) +
  geom_histogram(color = "black", fill = "steelblue") +
    labs(x="Valência",y="Frequencia"))
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Tempo

ggplotly(ggplot(data = dados2, aes(x = tempo)) +
              geom_histogram(color = "black", fill = "steelblue") +
              labs(x = 'Bpm',y='Frequencia'))
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Duration

ggplotly(ggplot(data = dados2, aes(x = duration_ms)) +
  geom_histogram(color = "black", fill = "steelblue") +
  xlim(c(0,1e+06)) +
  labs(x = 'Duração',y="Frequencia"))
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## Warning: Removed 1 rows containing non-finite values (`stat_bin()`).

Time Signature

ggplotly(ggplot(data = dados2, aes(x = time_signature)) +
  geom_bar(color = "black", fill = "steelblue") +
  scale_x_continuous(breaks=seq(0,7,by=1)) +
  labs(x = 'Compasso',y="Frequencia"))

Correlação

corrplot(cor(dados3))

A variável acousticness tem alta correlação negativa com as variáveis energy e loudness, indicando que músicas acústicas tendem a não serem energéticas e altas. A variável valence tem alta correlação positiva com a variável danceability, o que implica que músicas dançáveis são mais positivas. Também, temos correlações menores entre loudness e instrumentalness (negativa) e acousticness e tempo (negativa).

Distâncias

Distancia pearson

res.dist <- get_dist(dados3, method = "pearson") # Correlation-based distance method
fviz_dist(res.dist, lab_size = 8) # Visualize the dissimilarity matrix

Distancia euclidiana

res.dist2 <- get_dist(dados3, method = "euclidian") # Correlation-based distance method
fviz_dist(res.dist2, lab_size = 8) # Visualize the dissimilarity matrix

Distancia Manhattan

res.dist3 <- get_dist(dados3, method = "manhattan") # Correlation-based distance method
fviz_dist(res.dist3, lab_size = 8) # Visualize the dissimilarity matrix

Distancia Minkowski

res.dist4 <- get_dist(dados3, method = "minkowski") # Correlation-based distance method
fviz_dist(res.dist4, lab_size = 8) # Visualize the dissimilarity matrix

Dendograma para Observações

hc <- eclust(dados3, "hclust", hc_metric = "euclidean", hc_method = "ward.D", k=100)
## Warning: The `<scale>` argument of `guides()` cannot be `FALSE`. Use "none" instead as
## of ggplot2 3.3.4.
## ℹ The deprecated feature was likely used in the factoextra package.
##   Please report the issue at <]8;;https://github.com/kassambara/factoextra/issueshttps://github.com/kassambara/factoextra/issues]8;;>.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
fviz_dend(hc, rect = TRUE, k=3, show_labels=FALSE)

A amostra apresenta clara distinção para 2 ou 3 grupos.

Dendrograma para Variáveis

var_cat <- dados2[,c(3,6,8,16)]

for (i in (1:4)) {
  var_cat[, i] <- factor(var_cat[, i])
}

library(ClustOfVar)
## Warning: package 'ClustOfVar' was built under R version 4.2.3
tree <- hclustvar(dados3, var_cat)
plot(tree)

K-Means Clustering

# normalização das variáveis 
dadosNorm <- as.data.frame(scale(dados3))

set.seed(1234)
dados_k2 <- kmeans(dadosNorm, centers = 3)
dados_k2$size
## [1]  93 124  60
dados_k2$size/nrow(dados3)
## [1] 0.3357401 0.4476534 0.2166065

O primeiro cluster tem 187 (70%) observações, enquanto que o segundo tem 22 (8%) e o terceiro 59 (22%).

aggregate(dados3, by=list(dados_k2$cluster), mean)
##   Group.1 popularity danceability    energy   loudness speechiness acousticness
## 1       1   23.78495    0.4975194 0.7766237  -6.517591  0.08687312   0.08145191
## 2       2   41.71774    0.6730484 0.6842984  -6.823032  0.13859032   0.29067718
## 3       3   32.55000    0.3871833 0.1806372 -20.486783  0.04780500   0.86416667
##   instrumentalness  liveness   valence    tempo duration_ms
## 1       0.36256560 0.1935774 0.3447989 135.2544    250215.1
## 2       0.03191833 0.2344540 0.5811935 118.3867    193675.6
## 3       0.67061295 0.1322383 0.2003737 104.1014    206118.2

Estas foram as principais características de cada cluster:

Primeiro - Maior popularidade, dançabilidade, volume, positividade, tempo e duração. Também, esse grupo apresentou menor acusticidade, poucas letras e alta energia. Isso implica que a amostra apresenta um grupo de músicas mais populares, com maior volume, mais positivas e mais dançáveis, que também contém menos elementos acústicos.

Segundo - Menor popularidade, dançabilidade e instrumentalidade, bem como mais letras e mais “liveness” (aspectos de músicas performadas ao vivo).

Terceiro - Menor energia, volume, “liveness”, valence, tempo, duração e menos letras. Além de maior acusticidade e instrumentalidade. Esse grupo aparenta conter músicas mais tristes e acústicas.

Otimizando k

# quantos clusters? 

bss <- numeric()
wss <- numeric()


for(i in 1:10){
  
  # For each k, calculate betweenss and tot.withinss
  bss[i] <- kmeans(dadosNorm, centers=i)$betweenss
  wss[i] <- kmeans(dadosNorm, centers=i)$tot.withinss
  
}

# Between-cluster sum of squares vs Choice of k
p3 <- qplot(1:10, bss, geom=c("point", "line"), 
            xlab="Number of clusters", ylab="Between-cluster sum of squares") +
  scale_x_continuous(breaks=seq(0, 10, 1)) +
  theme_bw()

# Total within-cluster sum of squares vs Choice of k
p4 <- qplot(1:10, wss, geom=c("point", "line"),
            xlab="Number of clusters", ylab="Total within-cluster sum of squares") +
  scale_x_continuous(breaks=seq(0, 10, 1)) +
  theme_bw()

# Subplot
grid.arrange(p3, p4, ncol=2)

A partir das somas de quadrados, 2 ou 3 clusters seriam ideais. O ganho da inclusao de mais clusters é em geral similar, com exceção da diferença entre 6 e 7 clusters.